<?php
/**
 * XGPHP 轻量级PHP框架
 * @link http://xgphp.xg3.cn
 * @version 2.0.0
 * @license http://www.apache.org/licenses/LICENSE-2.0
 * @author 讯高科技 <xungaokeji@qq.com>
*/
namespace xg;
use \helper\Arr;
use \helper\Date;
use \xg\facade\Config;

class Database {
	protected $connects = [];
	protected $where = null;
	protected $config = [];
	protected $query = [];
	
	public function __construct($config=null){
		if(is_null($config)){
			$config = Config::load('database');
		}
		if(is_array($config)){
			// 不覆盖子类配置
			$this->config=Arr::plus($this->config,$config);
		}
	}
	// 修改数据库配置
	public function config($name,$value=null){
		if(is_array($name)){
			$this->config=Arr::extend($this->config,$name);
		}else{
			$this->config[$name]=$value;
		}
		return $this;
	}
	// 重置查询条件等信息
	protected function reset(){
		$this->query=[];
		if($this->where){
			$this->where->reset();
		}
		return $this;
	}
	
	
	
	
	
	// ================ [数据更新] ================
	// 插入记录
	public function insert(array $data=[]){
		$this->time($this->config['create_time'])->time($this->config['update_time']);
		$data = $this->processIn($data);
		$result = $this->connect()->query($this->query)->insert($data);
		$this->reset();
		return $result;
	}
	// 更新记录
	public function update(array $data=[]) {
		$this->time($this->config['update_time']);
		$data = $this->processIn($data);
		$result = $this->connect()->update($data);
		$this->reset();
		return $result;
	}
	// 删除记录
	public function delete(int $id=0){
		if($id){
			$this->where($id);
		}
		$result = $this->connect()->delete($id);
		$this->reset();
		return $result;
	}
	// 增加某个字段的值
	public function inc($fields,float $num=1){
		$result = $this->connect()->inc($fields,$num);
		$this->reset();
		return $result;
	}
	// 减小某个字段的值
	public function dec($fields,float $num=1){
		$result = $this->connect()->dec($fields,$num);
		$this->reset();
		return $result;
	}
	
	
	
	
	
	// ================ [数据查询] ================
	// 查询数据列表
	public function select(){
		$data=$this->connect()->select();
		if(is_array($data)){
			$result=[];
			foreach($data as $datai){
				$result[]=$this->processOut($datai);
			}
			$this->reset();
			return $result;
		}
		return false;
	}
	// 查询一条数据
	public function find($id=null){
		if($id){
			$this->where($id);
		}
		$data=$this->connect()->find();
		if(is_array($data)){
			$result=$this->processOut($data);
			$this->reset();
			return $result;
		}
		return false;
	}
	// 查询数据列表并且返回带有键名的数组
	public function column($fields=null,$keyName=null){
		if($fields){
			if($fields!='*'){
				$fields=Arr::split($fields);
				if($keyName and !in_array($keyName,$fields)){
					$fields[]=$keyName;
				}
			}
			$this->fields($fields);
		}
		$data=$this->select();
		if(is_array($data)){
			$result=[];
			foreach($data as $datai){
				$datai=$this->processOut($datai);
				if(!$keyName){
					$keyName = current(array_keys($datai));
				}
				$rowKey=$datai[$keyName];
				$result[$rowKey]=$datai;
			}
			return $result;
		}
		return false;
	}
	// 查询某个字段的值的列表
	public function values($fields=null){
		if($fields){
			$this->fields($fields);
		}
		$data=$this->select();
		if(is_array($data)){
			$result=[];
			foreach($data as $datai){
				$result[]=$this->processOut(current($datai));
			}
			return $result;
		}
		return false;
	}
	// 查询某个字段的值
	public function value($field){
		$this->fields($field);
		$result=$this->find();
		$result=$result?$result[$field]:false;
		return $result;
	}

	// 查询记录数量
	public function func(string $func,string $field='*'){
		$this->query['func']=[$func,$field];
		return $this;
	}
	
	// 查询记录数量
	public function count(){
		$result=$this->func('count')->find();
		return floatval(current($result));
	}
	// 查询某个字段的最大值
	public function max($f){
		$result=$this->func('max',$f)->find();
		return floatval(current($result));
	}
	// 查询某个字段的最小值
	public function min($f){
		$result=$this->func('min',$f)->find();
		return floatval(current($result));
	}
	// 查询某个字段的值的和
	public function sum($f){
		$result=$this->func('sum',$f)->find();
		return floatval(current($result));
	}
	// 查询某个字段的值的绝对值
	public function abs($f){
		$result=$this->func('abs',$f)->find();
		return floatval(current($result));
	}
	// 查询某个字段的值的平均值
	public function avg($f){
		$result=$this->func('avg',$f)->find();
		return floatval(current($result));
	}
	
	
	
	
	// ================ [查询条件] ================
	public function where($field,$operator=null,$value=null,$logical='and'){
		if(!$this->where){
			$this->where = new Where();
		}
		$this->where->where($field,$operator,$value,$logical);
		return $this;
	}
	// 或查询条件
	public function whereOr($field,$operator=null,$value=null){
		$this->where($field,$operator,$value,'or');
		return $this;
	}
	// 区间查询条件
	public function between($field,$start,$end,$logical='and'){
		return $this->where($field,'between',[$start,$end],$logical);
		return $this;
	}
	// 不在区间查询条件
	public function notBetween($field,$start,$end,$logical='and'){
		return $this->where($field,'not between',[$start,$end],$logical);
		return $this;
	}
	// null查询条件
	public function isNull($field,$logical='and'){
		return $this->where($field,'null',null,$logical);
		return $this;
	}
	// not null查询条件
	public function notNull($field,$logical='and'){
		return $this->where($field,'not null',null,$logical);
		return $this;
	}
	
	
	
	
	// ================ [查询方法] ================
	// 设置表的别名
	public function alias($name){
		$this->query['alias']=$name;
		return $this;
	}
	// 设置表名
	public function table($table=null){
		$this->query['table']=$table;
		return $this;
	}
	// 设置不带前缀的表名
	public function name($name){
		$this->query['name']=$name;
		return $this;
	}
	// 设置表名前缀
	public function prefix($prefix){
		$this->query['prefix']=$prefix;
		return $this;
	}

	// 增加查询的字段
	public function with($fields=null){
		$this->query['with']=array_unique(Arr::merge($this->query['with'],$fields));
		return $this;
	}
	// 排除查询的字段
	public function without($fields=null){
		$this->query['without']=array_unique(Arr::merge($this->query['without'],$fields));
		return $this;
	}
	// 设置主键
	public function pk($pk){
		$this->query['pk']=$pk;
		return $this;
	}
	// 设置查询字段
	public function fields($fields=null){
		$this->query['fields']=Arr::split($fields);
		return $this;
	}
	// 查询排序方式
	public function order($order){
		if(!stripos($order,' asc') and !stripos($order,' desc')){
			$order=$order.' asc';
		}
		$this->query['order']=$order;
		return $this;
	}
	// 查询分组方式
	public function group($group){
		$this->query['group']=$this->query['group']?$this->query['group']:[];
		$this->query['group']=array_unique(Arr::extend($this->query['group'],Arr::split($group)));
		return $this;
	}
	// 查询记录限制区间
	public function limit($start,$limit=null){
		if(is_numeric($start) and is_numeric($limit)){
			$this->query['limit']=$start.','.$limit;
		}else{
			$this->query['limit']=$start;
		}
		return $this;
	}
	// 查询记录分页信息
	public function page($page,$pagesize=12){
		if(is_array($page)){
			if($page[0] and $page[1]){
				$pagesize=$page[1];
				$page=$page[0]; // 此行代码和上一行代码顺序不能改变
			}elseif($page['page'] and $page['pagesize']){
				$pagesize=$page['pagesize'];
				$page=$page['page']; // 此行代码和上一行代码顺序不能改变
			}
		}
		$page=floatval($page);
		$pagesize=floatval($pagesize);
		if($page>0 and $pagesize>0){
			$this->limit((($page-1)*$pagesize).','.$pagesize);
		}
		return $this;
	}
	
	
	
	// ================ [数据处理] ================
	// 设置查询结果缓存信息
	public function cache($name,$time=0){
		$this->config['cache']=$name;
		$this->config['cachetime']=$time;
		return $this;
	}
	// 设置时间自动处理事件的字段
	public function time($fields,$format=null){
		$this->config['time_fields']=array_unique(Arr::merge($this->config['time_fields'],$fields));
		if(is_string($format)){
			$this->config['time_format']=$format;
		}
		return $this;
	}
	// 设置时间自动处理事件的字段
	public function time_format($format){
		$this->config['time_format']=$format;
		return $this;
	}
	// 设置以json形式存储数据的字段列表
	public function json($fields=null){
		$this->config['json_fields']=$fields;
		return $this;
	}
	public function processIn(array $data){
		if($time=$this->config['time_fields']){
			foreach($time as $field){
				if(!$data[$field]){
					$data[$field]=time();
				}
			}
		}
		if($json=$this->config['json_fields']){
			foreach($json as $field){
				$data[$field]=json_encode($data[$field]);
			}
		}
		return $data;
	}
	public function processOut(array $data){
		$this->time($this->config['update_time'])->time($this->config['create_time']);
		foreach($this->config['time_fields'] as $field){
			if(isset($data[$field])){
				$data[$field]=Date::format($data[$field],$this->config['time_format']);
			}
		}
		if($json=Arr::split($this->config['json_fields'])){
			foreach($json as $field){
				if(isset($data[$field])){
					$data[$field]=json_decode($data[$field],true);
				}
			}
		}
		return $data;
	}
	
	
	
	// ================ [驱动连接] ================
	protected function connect(string $type=''){
		$type = $type?$type:$this->config['default'];
		if(!$this->connects[$type]){
			$options = $this->config['connections'][$type];
			$drive = '\\xg\\database\\'.ucwords($options['type']);
			if(!class_exists($drive)){
				throw new Exception(\xg\facade\Lang::get('connector {:drive} not exists',['drive'=>$drive]));
			}
			$this->connects[$type] = new $drive($options);
		}
		return $this->connects[$type]->query($this->query)->where($this->where);
	}
}
?>